package com.example.springdataelastci.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.Result;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.CreateResponse;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import com.example.springdataelastci.model.BlogModel;
import com.example.springdataelastci.model.vo.BlogSelVo;
import com.example.springdataelastci.service.IBlogService;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

/**
 * 服务类
 *
 * @author heyangyang
 * @since 2023-11-13
 */
@Service
@Slf4j
public class BlogServiceImpl implements IBlogService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    public static final String INDEX_NAME = "blog";

    @Override
    public void insert(BlogModel blogModel) throws IOException {
        createIndex();

        boolean exists = elasticsearchClient.exists(
                req -> req.index(INDEX_NAME)
                        .id(blogModel.getId())
        ).value();

        if (exists) {

            Result result = elasticsearchClient.update(
                    u -> u.index(INDEX_NAME)
                            .id(blogModel.getId())
                            .doc(blogModel)
                    , BlogModel.class).result();
            log.info("更新数据了: {}" + result);
            return;
        }
        CreateResponse createResponse = elasticsearchClient.create(
                req -> req.index(INDEX_NAME)
                        .id(blogModel.getId())
                        .document(blogModel)

        );

        log.info("索引：{}, 文档:{}, 是否创建成功:{}", INDEX_NAME, blogModel.getId(), createResponse.result());
    }

    /**
     * 根据主键获取文档信息
     *
     * @param id 主键id
     * @return 文档信息
     * @throws IOException
     */
    @Override
    public BlogModel getById(String id) throws IOException {
        createIndex();
        GetResponse<BlogModel> getResponse =
                elasticsearchClient.get(u -> u.index(INDEX_NAME).id(id), BlogModel.class);

        return getResponse.source();
    }

    /**
     * 批量删除文档信息
     *
     * @param idList id集合
     * @throws IOException
     */
    @Override
    public void deleteByIdList(List<String> idList) throws IOException {
        createIndex();

        if (CollUtil.isEmpty(idList)) {
            return;
        }

        List<BulkOperation> bulkRequestList = Lists.newArrayList();

        for (String id : idList) {
            DeleteOperation build = new DeleteOperation.Builder()
                    .index(INDEX_NAME)
                    .id(id).build();
            final BulkOperation bulk = new BulkOperation.Builder().delete(build).build();
            bulkRequestList.add(bulk);
        }
        BulkRequest bulkRequest = new BulkRequest.Builder()
                .operations(bulkRequestList)
                .build();
        BulkResponse bulk = elasticsearchClient.bulk(bulkRequest);
        System.out.println("批量数据操作成功" + bulk);

        for (BulkResponseItem item : bulk.items()) {
            log.info("{}", item);
        }
    }

    @Override
    public List<BlogModel> page(BlogSelVo blogSelVo) throws IOException {
        createIndex();


        SearchRequest.Builder searchRequest = new SearchRequest.Builder().index(INDEX_NAME);
        MatchQuery.Builder matchQuery = new MatchQuery.Builder();
        if (StrUtil.isNotBlank(blogSelVo.getId())) {
            matchQuery.field("id").query(blogSelVo.getId());
        }

        if (StrUtil.isNotBlank(blogSelVo.getTitle())) {
            matchQuery.field("title").query(blogSelVo.getTitle());
        }

        Query query = new Query.Builder().match(matchQuery.build()).build();

        searchRequest.query(query).from((blogSelVo.getPageNum() - 1) * blogSelVo.getPageSize()).size(blogSelVo.getPageSize());
        SearchResponse<BlogModel> search = elasticsearchClient.search(searchRequest.build(), BlogModel.class);

        TotalHits total = search.hits().total();
        log.info("分页总数：{}", total.value());

        List<BlogModel> results = Lists.newArrayList();
        for (Hit<BlogModel> hit : search.hits().hits()) {
            BlogModel source = hit.source();
            results.add(source);
        }
        return results;
    }


    private void createIndex() throws IOException {
        boolean exists = elasticsearchClient.indices().exists(req -> req.index(INDEX_NAME)).value();
        if (exists) {
            return;
        }
        CreateIndexResponse respose = elasticsearchClient.indices().create(req -> req.index(INDEX_NAME));
        log.info("索引：{}, 是否创建成功：{}", INDEX_NAME, respose.acknowledged());
    }

}
